package com.adv.ems.model.dto;

import cn.hutool.core.date.DateUtil;
import com.adv.ems.db.entity.*;
import com.adv.ems.enums.DateTypeEnum;
import com.adv.ems.utils.EmsUtil;
import lombok.Data;
import java.util.*;
import java.util.stream.Collectors;

@Data
public class QueryPointEnergyResultDTO {
    private String groupKey;
    private Long pointId;
    private Date date;
    private Double firstRealValue;
    private Double lastRealValue;
    private Double increaseRealValue;
    private Double increaseStandValue;
    private Double increaseCashValue;

    public QueryPointEnergyResultDTO() {
        this.increaseCashValue = 0.0;
        this.increaseStandValue = 0.0;
        this.increaseRealValue = 0.0;
        this.firstRealValue = 0.0;
        this.lastRealValue = 0.0;
    }

    public static List<QueryPointEnergyResultDTO> groupByDate(List<QueryPointEnergyResultDTO> list, Long energyId, DateTypeEnum dateType, Boolean processData) {
        List<QueryPointEnergyResultDTO> result = new ArrayList<QueryPointEnergyResultDTO>();
        Map<Date, List<QueryPointEnergyResultDTO>> group = list.stream().collect(Collectors.groupingBy(data -> {
            if (DateTypeEnum.hour.equals(dateType)) {
                String date = DateUtil.format(data.getDate(), "yyyy-MM-dd HH:") + "00:00";
                return DateUtil.parseDateTime(date);
            }
            if (DateTypeEnum.day.equals(dateType)) {
                String date = DateUtil.format(data.getDate(), "yyyy-MM-dd") + " 00:00:00";
                return DateUtil.parseDateTime(date);
            }
            if (DateTypeEnum.month.equals(dateType)) {
                String date = DateUtil.format(data.getDate(), "yyyy-MM") + "-01 00:00:00";
                return DateUtil.parseDateTime(date);
            }
            if (DateTypeEnum.year.equals(dateType)) {
                String date = DateUtil.format(data.getDate(), "yyyy") + "-01-01 00:00:00";
                return DateUtil.parseDateTime(date);
            }
            return data.getDate();
        }));
        for (Map.Entry<Date, List<QueryPointEnergyResultDTO>> entry : group.entrySet()) {
            Date date = entry.getKey();
            List<QueryPointEnergyResultDTO> values = entry.getValue();
            QueryPointEnergyResultDTO dto = new QueryPointEnergyResultDTO();
            dto.setDate(date);
            if (!processData) {
                Double increaseRealValue = 0d;
                Double increaseStandValue = 0d;
                Double increaseCashValue = 0d;
                for (QueryPointEnergyResultDTO d : values) {
                    increaseCashValue += d.getIncreaseCashValue();
                    increaseStandValue += d.getIncreaseStandValue();
                    if (energyId != null) {
                        increaseRealValue += d.getIncreaseRealValue();
                    }
                }
                dto.setIncreaseRealValue(increaseRealValue);
                dto.setIncreaseStandValue(increaseStandValue);
                dto.setIncreaseCashValue(increaseCashValue);
            }else {
                QueryPointEnergyResultDTO d = values.get(values.size() - 1);
                dto.setIncreaseRealValue(d.getIncreaseRealValue());
            }
            result.add(dto);
        }
        return result.stream().sorted(Comparator.comparing(QueryPointEnergyResultDTO::getDate)).collect(Collectors.toList());
    }

    public static Map<String, QueryPointEnergyResultDTO> groupByNext(Long energyId, Long itemId, Long itemOneId, List<QueryPointEnergyResultDTO> list,
                                                                     Map<Long, MeterDO> meterMap,
                                                                     Map<Long, CollectPointDO> pointMap,
                                                                     Map<Long, ItemInfoDO> itemMap,
                                                                     Map<Long, ItemOneInfoDO> itemOneMap,
                                                                     Map<Long, ItemTwoInfoDO> itemTwoMap,
                                                                     String acceptLanguage) {
        Map<String, List<QueryPointEnergyResultDTO>> collect = list.stream().filter(d -> {
            CollectPointDO pointDO = pointMap.get(d.getPointId());
            if (pointDO == null || pointDO.getMeterId() == null) {
                return false;
            }
            MeterDO meterDO = meterMap.get(pointDO.getMeterId());
            if (meterDO == null) {
                return false;
            }
            ItemInfoDO itemInfoDO = meterDO.getItemId() != null ? itemMap.get(meterDO.getItemId()): null;
            ItemOneInfoDO itemOneInfoDO = meterDO.getItemOneId() != null ? itemOneMap.get(meterDO.getItemOneId()): null;
            ItemTwoInfoDO itemTwoInfoDO = meterDO.getItemTwoId() != null ? itemTwoMap.get(meterDO.getItemTwoId()): null;
            if (itemOneId != null) {
                if (itemTwoInfoDO == null) {
                    return false;
                }
                d.setGroupKey(EmsUtil.multilingual(itemTwoInfoDO.getNameInfo(), acceptLanguage));
            }else if (itemId != null) {
                if (itemOneInfoDO == null) {
                    return false;
                }
                d.setGroupKey(EmsUtil.multilingual(itemOneInfoDO.getNameInfo(), acceptLanguage));
            }else if (energyId != null) {
                if (itemInfoDO == null) {
                    return false;
                }
                d.setGroupKey(EmsUtil.multilingual(itemInfoDO.getNameInfo(), acceptLanguage));
            }else {
                return false;
            }
            return true;
        }).collect(Collectors.groupingBy(QueryPointEnergyResultDTO::getGroupKey));
        Map<String, QueryPointEnergyResultDTO> result = new HashMap<String, QueryPointEnergyResultDTO>();
        for (Map.Entry<String, List<QueryPointEnergyResultDTO>> entry : collect.entrySet()) {
            QueryPointEnergyResultDTO item = new QueryPointEnergyResultDTO();
            double increaseRealValue = 0d;
            double increaseStandValue = 0d;
            double increaseCashValue = 0d;
            for (QueryPointEnergyResultDTO d : entry.getValue()) {
                increaseStandValue += d.getIncreaseStandValue();
                increaseRealValue += d.getIncreaseRealValue();
            }
            item.setIncreaseRealValue(increaseRealValue);
            item.setIncreaseStandValue(increaseStandValue);
            item.setIncreaseCashValue(increaseCashValue);
            result.put(entry.getKey(), item);
        }
        return result;
    }

    public static Map<String, QueryPointEnergyResultDTO> groupByEnergyName(List<QueryPointEnergyResultDTO> list,
                                                                         Map<Long, CollectPointDO> pointMap,
                                                                         Map<Long, MeterDO> meterMap,
                                                                         Map<Long, EnergyInfoDO> energyInfoMap,
                                                                         String acceptLanguage) {
        Map<String, List<QueryPointEnergyResultDTO>> collect = list.stream().filter(d -> {
            CollectPointDO pointDO = pointMap.get(d.getPointId());
            if (pointDO == null || pointDO.getMeterId() == null) {
                return false;
            }
            MeterDO meter = meterMap.get(pointDO.getMeterId());
            if (meter == null || meter.getEnergyId() == null) {
                return false;
            }
            EnergyInfoDO energyInfoDO = energyInfoMap.get(meter.getEnergyId());
            if (energyInfoDO == null) {
                return false;
            }
            d.setGroupKey(EmsUtil.multilingual(energyInfoDO.getNameInfo(), acceptLanguage));
            return true;
        }).collect(Collectors.groupingBy(QueryPointEnergyResultDTO::getGroupKey));
        Map<String, QueryPointEnergyResultDTO> result = new HashMap<String, QueryPointEnergyResultDTO>();
        for (Map.Entry<String, List<QueryPointEnergyResultDTO>> entry : collect.entrySet()) {
            QueryPointEnergyResultDTO item = new QueryPointEnergyResultDTO();
            double increaseRealValue = 0d;
            double increaseStandValue = 0d;
            double increaseCashValue = 0d;
            for (QueryPointEnergyResultDTO d : entry.getValue()) {
                increaseStandValue += d.getIncreaseStandValue();
                increaseRealValue += d.getIncreaseRealValue();
                increaseCashValue += d.getIncreaseCashValue();
            }
            item.setIncreaseRealValue(increaseRealValue);
            item.setIncreaseStandValue(increaseStandValue);
            item.setIncreaseCashValue(increaseCashValue);
            result.put(entry.getKey(), item);
        }
        return result;
    }

    public static QueryPointEnergyResultDTO sumAll(List<QueryPointEnergyResultDTO> nowList) {
        QueryPointEnergyResultDTO result = new QueryPointEnergyResultDTO();
        double increaseStandValue = 0d;
        double increaseCashValue = 0d;
        for (QueryPointEnergyResultDTO d : nowList) {
            increaseStandValue += d.getIncreaseStandValue();
            increaseCashValue += d.getIncreaseCashValue();
        }
        result.setIncreaseStandValue(increaseStandValue);
        result.setIncreaseCashValue(increaseCashValue);
        return result;
    }
}
